/*File Name		: DateTime.h*/
/*Date			: 31-10-2012 */
/*Maker Name	: Muhammad Ghufron Mahfudhi (23512066) */
/*Mengimplementasikan Class DateTime*/

#include "DateTime.h"

/** Validator **/
int DateTime::IsDTValid(int D, int M, int Y, int h, int m, int s)
/* Mengembalikan 1 jika elemen date dan time valid */
{
	return ((D >= 1) && (M >= 1) && (M <=12) && (Y >= 1970) && (((M == 1) || (M == 3) || (M == 5) || (M == 7) || (M == 8) || (M == 10) || (M == 12))? (D <= 31) : (((M == 4) || (M == 6) || (M == 9) || (M == 11))? (D <= 30) : ((M == 2)? ((IsKabisat (Y))? (D <= 29) : (D <= 28)) : 0)))) && ((h >= 0) && (h<=23) && (m >= 0) && (m <= 59) &&(s >= 0) && (s <= 59));
}

int DateTime::IsKabisat (int Y)
/*	Menghasilkan 1 jika tahun Y adalah tahun kabisat yaitu habis dibagi 4 tetapi tidak habis dibagi 100, atau habis dibagi 400 */
{
	/* ALGORITMA */
	return ((((Y % 4) == 0) && ((Y % 100) != 0)) || ((Y % 400) == 0));
}
		
/** 4 sekawan **/
DateTime::DateTime()
/* Constructor: membuat DateTime default: banyak detik saat ini sejak 1 Januari 1970 */
{
	T = time(0);
}

DateTime::DateTime(int DD, int MM, int YY, int h, int m, int s)
/* Constructor: membuat DateTime berdasarkan parameter date dan time */
/* Prekondisi: parameter date dan time sudah valid */
{
	struct tm *timeinfo;
	timeinfo = localtime(&T);
	timeinfo->tm_year = YY - 1900;
	timeinfo->tm_mon = MM - 1;
	timeinfo->tm_mday = DD;
	timeinfo->tm_hour = h;
	timeinfo->tm_min = m;
	timeinfo->tm_sec = s;
	T = mktime(timeinfo);
}

DateTime::DateTime(string s)
/* Constructor: membuat DateTime berdasarkan string */
/* Prekondisi: format string sudah valid sudah valid */
{
	MakeFromString(s);
}
		
DateTime::DateTime(const DateTime& DT)
/* Copy constructor */
{
	T = DT.T;
}

DateTime& DateTime::operator=(const DateTime& DT)
/* Overloading operator = */
{
	T = DT.T;
	return *this;
}

DateTime::~DateTime()
/* Destructor */
{

}

/** Getter & Setter **/
time_t DateTime::GetT()
/* Mengembalikan t */
{
	return this->T;
}

void DateTime::SetT(const time_t& t)
/* Mengeset t dengan _t */
/* I.S. DateTime sudah terbentuk */
/* F.S. T sesuai dengan parameter */
{
	this->T = t;
}

/** Method **/
void DateTime::AddTime(int second)
/* Menambah t sebanyak second detik */
{
	this->T += second;
}

int operator<(const DateTime& D1, const DateTime& D2)
/* Overload operator <, Mengembalikan 1 jika D2 < D1 */
{
	return D2.T < D1.T;
}

/** Override method **/
void DateTime::Print()
/* I.S. dateTime terdefinisi */
/* F.S. Nilai dateTime ditulis ke layar beserta komponen-komponennya */
/* Proses : Menulis nilai setiap komponen dateTime ke layar */
{
	cout << ToString();

}

void DateTime::Read()
/* I.S. Sembarang */
/* F.S. dateTime terdefinisi dan merupakan dateTime yang valid */
/* Proses : Membaca komponen dateTime dari masukan pengguna */
{
	//Kamus Lokal
	int D, M, Y, h, m, s;
	//Algoritma
	cout << "  Membuat tanggal dan jam:\n";
	do{
		cout << "    Masukkan DD : "; cin >> D;
		cout << "    Masukkan MM : "; cin >> M;
		cout << "    Masukkan YYYY : "; cin >> Y;
		cout << "    Masukkan HH : "; cin >> h;
		cout << "    Masukkan MM : "; cin >> m;
		cout << "    Masukkan SS : "; cin >> s;
	} while (! (IsDTValid (D, M, Y, h, m, s)));
	DateTime Hasil(D, M, Y, h, m, s);
	this->T = Hasil.GetT();
}

string DateTime::ToString()
/* Mengembalikan DateTime dalam format "DD/MM/YYYY hh:mm:ss" */
{
	char hasil[20];
	strftime(hasil, 20, "%d/%m/%Y %X", localtime(&T));
	return string(hasil);
}

void DateTime::MakeFromString(string s)
/* Membentuk DateTime dari elemen yang bertipe string dengan format dd/mm/yyyy hh:mm:ss */
{
	//parsing string menjadi vektor integer
	vector<int> parseDT;
	int tempInt;
	string tempStr = s;
	string p = s;
	int delim = p.find_first_of("/ :");
	while (delim != string::npos){
		p = tempStr.substr(0,delim);
		stringstream ss(p);
		if(ss >> tempInt){
			parseDT.push_back(tempInt);
		}else{
			cout << "Bukan Integer\n";
		}
		tempStr = tempStr.substr(delim+1,tempStr.length()-delim+1);
		delim = tempStr.find_first_of("/ :");
	}
	stringstream ss(tempStr);
	if(ss >> tempInt){
		parseDT.push_back(tempInt);
	}else{
		cout << "Bukan Integer\n";
	}
	
	//membuat datetime
	DateTime Hasil(parseDT[0], parseDT[1], parseDT[2], parseDT[3], parseDT[4], parseDT[5]);
	this->T = Hasil.GetT();
}
